home *** CD-ROM | disk | FTP | other *** search
- Path: news.th-darmstadt.de!news
- From: enno@inferenzsysteme.informatik.th-darmstadt.de (Enno Sandner)
- Newsgroups: comp.lang.c++
- Subject: Re: Mutually referring header files
- Date: 10 Apr 1996 19:31:52 +0200
- Organization: Fachbereich Informatik, TH Darmstadt
- Sender: enno@kitz.inferenzsysteme.informatik.th-darmstadt.de
- Message-ID: <lt91g4ouif.fsf@kitz.inferenzsysteme.informatik.th-darmstadt.de>
- References: <4ked7q$8g3@dub-news-svc-1.compuserve.com>
- NNTP-Posting-Host: kitz.intellektik.informatik.th-darmstadt.de
- In-reply-to: RossBoylan@aol.com's message of Tue, 09 Apr 1996 19:22:49 GMT
- X-Newsreader: Gnus v5.1
-
- In article <4ked7q$8g3@dub-news-svc-1.compuserve.com> RossBoylan@aol.com (Ross Boylan) writes:
-
- I have 2 classes A + B, defined in separate files. Each refers to and
- messages the other. What is the best way to handle this?
-
- 1) My naive approach was
- a.h----------------------------------------------------------
- #ifndef ah
- #define ah
- #include "b.h:
- class A {
- public:
- void hello();
- private:
- B *pB;
- //etc
- };
- #endif
-
- b.h------------------------------------------------------------
- #ifndef bh
- #define bh
- #include "a.h"
- class B{
- public:
- void hello();
- private:
- A *pA;
- };
- #endif
- -------------------------------------------------------------------
- The #ifndef's prevent infinite recursion, but if we start with
- #include "a.h"
- this will then include "b.h"
- b.h will skip a.h since the symbol ah is already defined.
- So when we get to the line A *pA in b.h, A has not yet been defined
- and we get an error.
-
- 2) My less naive approach was to add the declaration
- class A;
- to b.h. This works, but seems awfully obscure, since on the face of
- it the code
- "include a.h"
- class A;
- is redundant.
- Also when you multiply this by a bunch of classes referencing each
- other, it gets pretty messy. In particular if you add a subclass of A
- to the a.h file, and then want to refer to it from elsewhere, you must
- add the declaration for this class to all the consumers.
-
-
- 3) It may or may not matter that I'm actually using smart pointers, so
- the pointer declarations are actually
- CountedObjPtr<A> pA;
-
- 4)
- Also, I put no code definition in the header file (i.e., b.h contains
- no lines of the form
- class B {
- void doit() {pA->hello();};
- };
- Such lines require more than class A;--they must actually know the
- protocols A responds to.
-
- This bit of code discipline is possible for regular classes, but what
- do I do for templates. With my compiler (MSVC++ 4.0) the header file
- must include all the code definition.
-
- I see mainly two solutions:
- 1) Use forward declarations and put the appropriate include-command
- in implementation not in the header-file.
- 2) Avoid cyclic dependencies by introducing abstract classes.
- For instance, instead of let A maintain a pointer to the concrete
- class 'B', ask yourself what kind of services 'A' uses from 'B'
- and make them explicit in an suitable interface, which the class
- 'B' has to conform to.
- Say 'A' uses the services 'void f1()' and 'void f2()' from 'B'.
- The abstract class 'BBase' represents the interface available
- for 'A' to use services from 'B'.
-
- class BBase {
- public:
- virtual ~BBase() {}
- void f1()=0;
- void f2()=0;
- // BBase may need an additional Clone method
- };
-
- 'A' maintains a pointer to a BBase-object instead and 'B' conforms to
- the BBase interface which is expressed by using public inheritence.
-
- Enno
-